﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AcmeSportsStore
{
    class CustomersStore
    {
        protected CustomersItemIndexerByAddress cIndexerByAddress
            = new CustomersItemIndexerByAddress();

        protected CustomersItemIndexerById cIndexerById
            = new CustomersItemIndexerById();

        protected CustomersItemIndexerByName cIndexerByName
            = new CustomersItemIndexerByName();

        protected CustomersItemIndexerByPhone cIndexerByPhone
            = new CustomersItemIndexerByPhone();

        public CustomersStore()
        { 
        }

        public int Count
        {
            get
            {
                return cIndexerById.Count;
            }
        }

        public CustomersItem GetItemByIndexerForId(int index)
        {
            return (CustomersItem)cIndexerById[index];
        }

        public CustomersItem GetItemByIndexerForName(int index)
        {
            return (CustomersItem)cIndexerByName[index];
        }

        public CustomersItem GetItemByIndexerForAddress(int index)
        {
            return (CustomersItem)cIndexerByAddress[index];
        }

        public CustomersItem GetItemByIndexerForPhone(int index)
        {
            return (CustomersItem)cIndexerByPhone[index];
        }

        public int GetIndexForId(CustomersItem item)
        {
            return cIndexerById.GetIndex(item);
        }

        public int GetIndexForName(CustomersItem item)
        {
            return cIndexerByName.GetIndex(item);
        }

        public int GetIndexForAddress(CustomersItem item)
        {
            return cIndexerByAddress.GetIndex(item);
        }

        public int GetIndexForPhone(CustomersItem item)
        {
            return cIndexerByPhone.GetIndex(item);
        }

        //
        public int GetIndexForIdById(int id)
        {
            /*
             * this is a just a temporary object for the 
             * searching to compare against
             */
            CustomersItem dummy = new CustomersItem(id, "", "", 0);

            return cIndexerById.GetIndex(dummy);
        }

        /*
         * get all the indices to objects that have
         * a name equal to the specified name
         */
        public bool GetIndicesForNameByName(string name, out int first,
            out int count)
        {
            CustomersItem dummy = new CustomersItem(0, name, "", 0);

            return cIndexerByName.GetIndices(dummy,
                out first, out count);
        }

        /*
         * get all the indices to objects that have
         * a description equal to the specified description
         */
        public bool GetIndicesForAddressByAddress(string address,
            out int first, out int count)
        {
            CustomersItem dummy = new CustomersItem(0, "", address, 0);

            return cIndexerByAddress.GetIndices(dummy,
                out first, out count);
        }

        /*
         * get all the indices to objects that have
         * a price equal to the specified price
         */
        public bool GetIndicesForPhoneByPhone(long phone,
            out int first, out int count)
        {
            CustomersItem dummy = new CustomersItem(0, "", "", phone);

            return cIndexerByPhone.GetIndices(dummy,
                out first, out count);
        }

        public void Clear()
        {
            cIndexerById.Clear();
            cIndexerByName.Clear();
            cIndexerByAddress.Clear();
            cIndexerByPhone.Clear();
        }

        public bool AddItem(CustomersItem item)
        {
            int index = cIndexerById.Add(item);

            if (index < 0)
            {   /* already exists */
                return false;
            }

            /*
             * since it is accepted by id indexer
             * it should be accepted by all the
             * other indexers
             */
            cIndexerByName.Add(item);
            cIndexerByAddress.Add(item);
            cIndexerByPhone.Add(item);
            return true;
        }

        public bool RemoveItemById(int id)
        {
            int index = this.GetIndexForIdById(id);
            if (index < 0)
            {   /* not found */
                return false;
            }
            /*
             * retrieve the actual object to be removed
             */
            SportsItem objToRemove = (SportsItem)cIndexerById[index];
            cIndexerById.RemoveAt(index);

            index = cIndexerByName.GetIndex(objToRemove);
            cIndexerByName.RemoveAt(index);

            index = cIndexerByAddress.GetIndex(objToRemove);
            cIndexerByAddress.RemoveAt(index);

            index = cIndexerByPhone.GetIndex(objToRemove);
            cIndexerByPhone.RemoveAt(index);

            return true;
        }

        public bool RemoveItemsByName(string name)
        {
            int first;
            int count;

            bool ok = this.GetIndicesForNameByName(name,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
                CustomersItem objToRemove = (CustomersItem)cIndexerByName[i];
                cIndexerByName.RemoveAt(i);
                /*
                 * process the other three indexers
                 */
                int index = cIndexerById.GetIndex(objToRemove);
                cIndexerById.RemoveAt(index);

                index = cIndexerByAddress.GetIndex(objToRemove);
                cIndexerByAddress.RemoveAt(index);

                index = cIndexerByPhone.GetIndex(objToRemove);
                cIndexerByPhone.RemoveAt(index);
            }
            return true;
        }


        public bool RemoveItemsByAddress(string address)
        {
            int first;
            int count;
            bool ok = this.GetIndicesForAddressByAddress(address,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
               CustomersItem objToRemove = (CustomersItem)cIndexerByAddress[i];
                cIndexerByAddress.RemoveAt(i);

                /*
                 * process the other three indexers
                 */
                int index = cIndexerById.GetIndex(objToRemove);
                cIndexerById.RemoveAt(index);

                index = cIndexerByName.GetIndex(objToRemove);
                cIndexerByName.RemoveAt(index);

                index = cIndexerByPhone.GetIndex(objToRemove);
                cIndexerByPhone.RemoveAt(index);

            }

            return true;
        }

        public bool RemoveItemsByPhone(long phone)
        {

            int first;
            int count;
            bool ok = this.GetIndicesForPhoneByPhone(phone,
                out first, out count);
            if (!ok)
            {   /* not found */
                return false;
            }

            /*
             * 'i' goes through all the indices returned above
             */
            for (int i = first; count >= 0; count--, i++)
            {
                /*
                 * retrieve the actual object to be removed
                 */
                CustomersItem objToRemove = (CustomersItem)cIndexerByPhone[i];
                cIndexerByPhone.RemoveAt(i);

                /*
                 * process the other three indexers
                 */
                int index = cIndexerById.GetIndex(objToRemove);
                cIndexerById.RemoveAt(index);

                index = cIndexerByName.GetIndex(objToRemove);
                cIndexerByName.RemoveAt(index);

                index = cIndexerByPhone.GetIndex(objToRemove);
                cIndexerByPhone.RemoveAt(index);
            }

            return true;
        }
    }
}
